﻿#include "dxstdafx.h"
#include "CharactersIO.h"
#include "Characters.h"

#define POINTERTRANSFORM(C)\
	C* cp = nullptr;\
	_stDate stDate; \
	if (stDate.SetYMDbyWstr(m_list_StartObjKey.back())) { _st_Annals* pAnnals = static_cast<_st_Annals*>(m_list_OperatorPtr.back()); CHECK_RETURN(pAnnals); cp = (C*)(pAnnals); }\
	else if (L"raise_levies" == m_list_StartObjKey.back()) { _st_raise_levies* pRL = static_cast<_st_raise_levies*>(m_list_OperatorPtr.back()); CHECK_RETURN(pRL); cp = (C*)(pRL); }\
	else { _stCharactersPorperty* pCP = static_cast<_stCharactersPorperty*>(m_list_OperatorPtr.back()); CHECK_RETURN(pCP); cp = (C*)(pCP); }\
	CHECK_RETURN(cp);\

// (C*)(m_list_OperatorPtr.back())->P = (*T)(vp)  普通赋值操作
#define NORMAL_ASSIGN(C, P, T)\
[this](const void* vp){	CHECK_RETURN(vp);\
		if (m_list_OperatorPtr.empty()) return;\
		if (m_list_StartObjKey.empty()) return;\
		const T* tp = static_cast<const T*>(vp);\
		CHECK_RETURN(tp);\
		POINTERTRANSFORM(C)\
		cp->P = *tp; }\

// (C*)(m_list_OperatorPtr.back())->P = true  赋值true
#define ASSIGN_TRUE(C, P)\
[this](const void* vp){	CHECK_RETURN(vp);\
		if (m_list_OperatorPtr.empty()) return;\
		if (m_list_StartObjKey.empty()) return;\
		POINTERTRANSFORM(C)\
		cp->P = true; }\

// (C*)(m_list_OperatorPtr.back())->P.push_back((*T)(vp))  push_back赋值操作
#define PUSHBACK_ASSIGN(C, P, T)\
[this](const void* vp){ CHECK_RETURN(vp);\
		if (m_list_OperatorPtr.empty()) return;\
		if (m_list_StartObjKey.empty()) return;\
		POINTERTRANSFORM(C)\
		const T* tp = static_cast<const T*>(vp);\
		CHECK_RETURN(tp);\
		cp->P.push_back(*tp); }\


CCharactersReaderHandle::CCharactersReaderHandle(std::unordered_map<int, _stCharactersPorperty>* map)
	: BaseReaderHandler(map)
{
	m_map_OperatorFunction = {
		{ L"name", NORMAL_ASSIGN(_st_IndexName, m_wstr_IndexName, std::wstring) },
		{ L"female", NORMAL_ASSIGN(_st_female, m_b_female, bool) },
		
		{ L"diplomacy", NORMAL_ASSIGN(_st_diplomacy, m_n_diplomacy, int) },
		{ L"martial", NORMAL_ASSIGN(_st_martial, m_n_martial, int) },
		{ L"stewardship", NORMAL_ASSIGN(_st_stewardship, m_n_stewardship, int) },
		{ L"intrigue", NORMAL_ASSIGN(_st_intrigue, m_n_intrigue, int) },
		{ L"learning", NORMAL_ASSIGN(_st_learning, m_n_learning, int) },

		{ L"dna", NORMAL_ASSIGN(_st_dna, m_wstr_dna, std::wstring) },
		{ L"properties", NORMAL_ASSIGN(_st_properties, m_wstr_properties, std::wstring) },
		{ L"culture", NORMAL_ASSIGN(_st_culture, m_wstr_culture, std::wstring) },
		{ L"religion", NORMAL_ASSIGN(_st_religion, m_wstr_religion, std::wstring) },
		{ L"dynasty", NORMAL_ASSIGN(_st_dynasty, m_n_dynasty, int) },
		{ L"father", NORMAL_ASSIGN(_st_father, m_n_father, int) },
		{ L"mother", NORMAL_ASSIGN(_st_mother, m_n_mother, int) },
		{ L"trait", PUSHBACK_ASSIGN(_st_trait, m_list_trait, std::wstring) },
		{ L"occluded",NORMAL_ASSIGN(_st_occluded, m_b_occluded, bool) },
		{ L"birth", ASSIGN_TRUE(_st_birth, m_b_birth) },
		{ L"death", ASSIGN_TRUE(_st_death, m_b_death) },
		{ L"death_reason", NORMAL_ASSIGN(_st_death_reason, m_wstr_death_reason, std::wstring ) },
		{ L"killer", NORMAL_ASSIGN(_st_killer, m_n_killer, int) },

		{ L"employer", NORMAL_ASSIGN(_st_employer, m_n_employer, int) },
		{ L"add_spouse", PUSHBACK_ASSIGN(_st_add_spouse, m_list_add_spouse, int) },
		{ L"remove_spouse", PUSHBACK_ASSIGN(_st_remove_spouse, m_list_remove_spouse, int) },
		{ L"add_matrilineal_spouse", PUSHBACK_ASSIGN(_st_add_matrilineal_spouse, m_list_add_matrilineal_spouse, int) },
		
		{ L"add_claim", PUSHBACK_ASSIGN(_st_add_claim, m_list_add_claim, std::wstring) },
		{ L"remove_claim", PUSHBACK_ASSIGN(_st_remove_claim, m_list_remove_claim, std::wstring) },
		{ L"give_nickname", PUSHBACK_ASSIGN(_st_give_nickname, m_list_give_nickname, std::wstring) },

		{ L"location", NORMAL_ASSIGN(_st_location, m_n_location, int) },
		{ L"force_mult", NORMAL_ASSIGN(_st_force_mult, m_f_force_mult, double) },

		{ L"raise_levies", NESTED_STRCUCT_PUSHBACK(_st_Annals, m_list_raise_levies, _st_raise_levies) },
	};
}

bool CCharactersReaderHandle::HandleBool(const std::wstring& key, bool b)
{
	if (m_bKeyInEffect)
	{
		return true;
	}
	else
	{
		return OperatorFunction(key, &b);
	}
	return true;
}

bool CCharactersReaderHandle::HandleInt(const std::wstring& key, int i)
{
	if (m_bKeyInEffect)
	{
		return true;
	}
	else
	{
		return OperatorFunction(key, &i);
	}
	return true;
}

bool CCharactersReaderHandle::HandleString(const std::wstring& key, const std::wstring& str)
{
	if (m_bKeyInEffect)
	{
		return true;
	}
	else
	{
		return OperatorFunction(key, &str);
	}
	return true;
}

bool CCharactersReaderHandle::HandleStartObj(const std::wstring& key)
{
	if (key.empty())
	{
		return BaseReaderHandler::HandleStartObj(key);
	}
	if (L"effect" == key)
	{
		m_bKeyInEffect = true;
	}
	if (m_bKeyInEffect)
	{
		return BaseReaderHandler::HandleStartObj(key);
	}
	// 要么是id 要么是date
	_stDate stDate;
	if (stDate.SetYMDbyWstr(key))
	{
		// 日期
		_stCharactersPorperty* pCP = static_cast<_stCharactersPorperty*>(m_list_OperatorPtr.back());
		CHECK_RE_FALSE(pCP);
		_st_Annals st_Annals;
		st_Annals.m_Date = stDate;
		pCP->m_list_Annals.push_back(st_Annals);
		m_list_OperatorPtr.push_back(&pCP->m_list_Annals.back());
	}
	else if (isdigit(key[0]))
	{
		// id
		_stCharactersPorperty st_value;
		st_value.m_id = _wtoi(key.c_str());
		CHECK_RE_FALSE(m_Container);
		auto iterInsertMap = m_Container->insert(std::make_pair(st_value.m_id, st_value));
		if (!iterInsertMap.second)
		{
			CString strError;
			strError.Format(L"characters id '%d' is repeat!", st_value.m_id);
			CommonFunc::ErrorMessageBox(strError);
			return false;
		}
		else
		{
			m_list_OperatorPtr.push_back(&iterInsertMap.first->second);
		}
	}
	else if (L"death" == key || L"raise_levies" == key)
	{
		return OperatorFunction(key, nullptr);
	}
	else
	{
		assert(0);
	}
	return BaseReaderHandler::HandleStartObj(key);
}

bool CCharactersReaderHandle::HandleEndObj()
{
	if (!m_list_StartObjKey.empty())
	{
		if (L"effect" == m_list_StartObjKey.back())
		{
			m_bKeyInEffect = false;
			return BaseReaderHandler::HandleEndObj();
		}
	}
	if (m_bKeyInEffect)
	{
		return BaseReaderHandler::HandleEndObj();
	}

	if (!m_list_OperatorPtr.empty())
	{
		m_list_OperatorPtr.pop_back();
	}
	return BaseReaderHandler::HandleEndObj();
}
